import 'package:flutter/material.dart';

import '../../../common/common.dart';
import '../../ui.dart';
import 'common/config.dart';
import 'widget/overlay_log_widget.dart';

enum DebugOverLaySize {
  min,
  small,
  normal,
  big,
}

class DebugOverLay {
  static const _tag = "DebugOverLay";
  static OverlayEntry? _holder;
  static bool get isShow => _holder != null;
  //static double width = 280;
  //static double height = 320;
  static DebugOverLaySize size = DebugOverLaySize.normal;
  static DebugOverLaySize? _lastSize;
  static double? _lastDx;
  static double? _lastDy;

  static double get width {
    switch (size) {
      case DebugOverLaySize.min:
        return 60;
      case DebugOverLaySize.small:
        return MyScreen.screenWidth / 2.5;
      case DebugOverLaySize.normal:
        return MyScreen.screenWidth / 1.5;
      case DebugOverLaySize.big:
        return MyScreen.screenWidth;
    }
  }

  static double get height {
    switch (size) {
      case DebugOverLaySize.min:
        return 60;
      case DebugOverLaySize.small:
        return 280;
      case DebugOverLaySize.normal:
        return 360;
      case DebugOverLaySize.big:
        return MyScreen.screenHeight / 2;
    }
  }

  static void hide() {
    if (_holder != null) {
      _holder?.remove();
      _holder = null;
    }
  }

  static void show({required BuildContext context, Widget? view}) {
    hide();

    size = _lastSize ?? DebugOverLaySize.normal;

    bool isLeft = true;
    if (_lastDx != null) {
      if (_lastDx! + (width / 2) > MediaQuery.of(context).size.width / 2) {
        isLeft = false;
      }
    }

    //创建一个OverlayEntry对象
    OverlayEntry overlayEntry = OverlayEntry(builder: (context) {
      return Positioned(
          top: _lastDy ?? 180,
          left: isLeft ? 0 : null,
          right: isLeft ? null : 0,
          child: _buildDraggable(context));
    });

    //往Overlay中插入插入OverlayEntry
    Overlay.of(context).insert(overlayEntry);

    _holder = overlayEntry;
  }

  static Widget _widget() {
    if (size == DebugOverLaySize.min) {
      return ClipRRect(
        borderRadius: BorderRadius.circular(8),
        child: Material(
          color: Colors.black87,
          child: InkWell(
            child: SizedBox(
              width: width,
              height: height,
              child: const Icon(
                Icons.bug_report_outlined,
                color: Colors.white,
                size: 30,
              ),
            ),
            onTap: () {
              size = _lastSize ?? DebugOverLaySize.normal;
              refresh();
            },
          ),
        ),
      );
    }

    return ClipRRect(
      borderRadius: BorderRadius.circular(8),
      child: Material(
        color: Colors.black87,
        child: SizedBox(
          width: width,
          height: height,
          child: OverlayLogWidget(
            showTime: overlayShowTime,
            logLevel: logLevel,
            onClosed: () {
              hide();
            },
            onGotoDebugPage: () {
              //hide();
              goto(() => const MyDebugPage());
            },
            onShowTimeChanged: (value) {
              overlayShowTime = value;
              refresh();
            },
            onSizeChanged: () {
              size = size == DebugOverLaySize.big
                  ? DebugOverLaySize.small
                  : DebugOverLaySize.values[size.index + 1];
              _lastSize = size;
              refresh();
            },
            onMinSize: () {
              size = DebugOverLaySize.min;
              refresh();
            },
            onLogLevelChanged: (value) {
              logLevel = value;
              refresh();
            },
          ),
        ),
      ),
    );
  }

  static _buildDraggable(context) {
    return Draggable(
      feedback: _widget(),
      onDragEnd: (detail) {
        //logd(_tag, 'onDragEnd:${detail.offset}');
        createDragTarget(offset: detail.offset, context: context);
      },
      childWhenDragging: Container(),
      child: _widget(),
    );
  }

  static void refresh() {
    _holder?.markNeedsBuild();
  }

  static void createDragTarget(
      {required Offset offset, required BuildContext context}) {
    if (_holder != null) {
      _holder?.remove();
    }

    _holder = OverlayEntry(builder: (context) {
      bool isLeft = true;

      final double dx = offset.dx < 0 ? 0 : offset.dx;

      if (offset.dx + (width / 2) > MediaQuery.of(context).size.width / 2) {
        isLeft = false;
      }

      double maxY = MediaQuery.of(context).size.height - height;

      final double dy = offset.dy < 50
          ? 50
          : offset.dy < maxY
              ? offset.dy
              : maxY;

      _lastDx = dx;
      _lastDy = dy;

      return Positioned(
          top: dy,
          left: isLeft ? 0 : null,
          right: isLeft ? null : 0,
          child: DragTarget(
            onWillAccept: (data) {
              //logd(_tag, 'onWillAccept: $data');
              return data != null;
            },
            onAccept: (data) {
              //logd(_tag, 'onAccept: $data');
              // refresh();
            },
            onLeave: (data) {
              //logd(_tag, 'onLeave');
            },
            builder: (BuildContext context, List incoming, List rejected) {
              return _buildDraggable(context);
            },
          ));
    });
    Overlay.of(context).insert(_holder!);
  }
}
